package com.yskj.mwk.service.impl;


import cn.hutool.core.util.StrUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.model.GetObjectRequest;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.ciModel.auditing.ImageAuditingRequest;
import com.qcloud.cos.model.ciModel.auditing.ImageAuditingResponse;
import com.yskj.mwk.service.UploadService;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.imaging.ImageReadException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.ImageWriteException;
import java.awt.image.BufferedImage;
import java.io.*;

@Service
public class UploadServiceImpl implements UploadService {

    private final Logger logger = LoggerFactory.getLogger(UploadServiceImpl.class);

    @Value("${upload.upload-path}/image/avatar/")
    private String avatarPath;

    @Value("${upload.upload-path}/image/common/")
    private String commonPath;

    @Value("${upload.upload-path}/image/resultpic/")
    private String resultPath;

    @Value("${upload.upload-path}/image/goods/")
    private String goodsPath;

    /**
     * 日期路径格式
     */
    private final String datePathFormat = "yyyy/MM/dd/";

    /**
     * 日期格式
     */
    private final SimpleDateFormat sdf = new SimpleDateFormat(datePathFormat);

    @Autowired
    private COSClient cosClient;

    @Autowired
    private COSClient cosClient2;

    @Value("${tencent.cos.bucketName}")
    private String bucketName;


    /**
     * 头像上传
     * */
    @Override
    public String uploadAvatarImage(String url, MultipartFile file) {

        //1.获取日期字符串
        String formatDate = sdf.format(new Date());

        //2.获取新文件名
        String newFileName = getNewFileName(file.getOriginalFilename());

        //3.保存图片

        //3.1 判断文件夹是否存在，不存在则创建
        String imageDirPath = avatarPath + formatDate;
        File imageDir = new File(imageDirPath);
        if (!imageDir.exists()){
            imageDir.mkdirs();
        }

        //3.2 拼接文件完整路径
        String imageFilePath = imageDirPath + "/" + newFileName;
        System.out.println(imageFilePath);

        //3.3 保存
        try {
            file.transferTo(new File(imageDir.getAbsoluteFile(), newFileName));

        } catch (Exception e){
            logger.error("文件 {} 保存失败", imageFilePath, e);
            return null;
        }
        logger.info("图片上传保存地址：{}",imageFilePath);
        //4.拼接请求路径

        //4.1 正则匹配请求前缀
        Pattern pattern = Pattern.compile("(.*)/upload.*");
        Matcher matcher = pattern.matcher(url);

        String urlPrefix = "http://localhost:18080";

        while(matcher.find()){
            urlPrefix = matcher.group(1);
        }
        String picUrl=urlPrefix + "/image/avatar/" + formatDate + newFileName;
        ImageAuditingRequest request = new ImageAuditingRequest();
        request.setBucketName(bucketName);
        request.setDetectUrl(picUrl); // 使用文件名作为URL（需提前上传至COS）

        // 调用审核接口
        ImageAuditingResponse response = cosClient.imageAuditing(request);
        logger.info("图片审核回调：{}",response);
        String result=response.getLabel();
        String res=response.getState();
        if (result.equals("Normal")&&res.equals("Success")){
            return picUrl;
        }else{
            return null;
        }
        //return picUrl;
    }

    /**
     * 用户前端上传图片路径
     * */
    @Override
    public String uploadCommonImage(String url, MultipartFile file) {
        //1.获取日期字符串
        String formatDate = sdf.format(new Date());

        //2.获取新文件名
        String newFileName = getNewFileName(file.getOriginalFilename());

        //3.保存图片

        //3.1 判断文件夹是否存在，不存在则创建
        String imageDirPath = commonPath + formatDate;
        File imageDir = new File(imageDirPath);
        if (!imageDir.exists()){
            imageDir.mkdirs();
        }

        //3.2 拼接文件完整路径
        String imageFilePath = imageDirPath + "/" + newFileName;
        System.out.println(imageFilePath);

        //3.3 保存
        try {
            file.transferTo(new File(imageDir.getAbsoluteFile(), newFileName));

        } catch (Exception e){
            logger.error("文件 {} 保存失败", imageFilePath, e);
            return null;
        }

        //4.拼接请求路径

        //4.1 正则匹配请求前缀
        Pattern pattern = Pattern.compile("(.*)/upload.*");
        Matcher matcher = pattern.matcher(url);

        String urlPrefix = "http://localhost:18080";

        while(matcher.find()){
            urlPrefix = matcher.group(1);
        }
        return urlPrefix + "/image/common/" + formatDate + newFileName;
    }


    /**
     * 合成图片保存地址
     * Base64
     * */
    @Override
    public String uploadBase64(String base64Data, String url) {
        try {
            byte[] imageBytes = Base64.getDecoder().decode(base64Data);

            // 2. 生成存储路径
            String formatDate = sdf.format(new Date());
            String imageDirPath = resultPath + formatDate;
            Files.createDirectories(new File(imageDirPath).toPath()); // 自动创建目录

            // 3. 读取图片并设置300dpi元数据
            String newFileName = System.currentTimeMillis() + ".png";
            String imageFilePath = imageDirPath + "/" + newFileName;

            try (InputStream inputStream = new ByteArrayInputStream(imageBytes)) {
                BufferedImage image = ImageIO.read(inputStream);
                if (image == null) {
                    throw new IllegalArgumentException("Invalid image format");
                }

                // 设置DPI元数据（针对PNG）
                ImageWriter writer = ImageIO.getImageWritersByFormatName("png").next();
                IIOMetadata metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(image), writer.getDefaultWriteParam());
                IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree("javax_imageio_1.0");
                IIOMetadataNode pHYs = new IIOMetadataNode("pHYs");
                double pixelsPerMeter = 300 * 100 / 2.54; // 300dpi转像素/米
                pHYs.setAttribute("hRes", String.valueOf(pixelsPerMeter));
                pHYs.setAttribute("vRes", String.valueOf(pixelsPerMeter));
                pHYs.setAttribute("unitSpecifier", "meters");
                root.appendChild(pHYs);
                metadata.setFromTree("javax_imageio_1.0", root);

                // 保存高DPI图片
                try (ImageOutputStream ios = ImageIO.createImageOutputStream(new File(imageFilePath))) {
                    writer.setOutput(ios);
                    writer.write(metadata, new IIOImage(image, null, metadata), null);
                }
                writer.dispose();
            }

            // 4. 生成访问URL
            Pattern pattern = Pattern.compile("(.*)/upload.*");
            Matcher matcher = pattern.matcher(url);
            String urlPrefix = matcher.find() ? matcher.group(1) : "http://localhost:18080";
            return urlPrefix + "/image/resultpic/" + formatDate + "/" + newFileName; // 修复路径缺少斜杠问题
        } catch (Exception e) {
            e.printStackTrace(); // 实际应记录日志
            return null;
        }
    }

    /**
     * 合成图片保存地址
     * 文件流
     * */
    @Override
    public String uploadResultImage(String url, MultipartFile file) {
        //1.获取日期字符串
        String formatDate = sdf.format(new Date());

        //2.获取新文件名
        String newFileName = getNewFileName(file.getOriginalFilename());

        //3.保存图片

        //3.1 判断文件夹是否存在，不存在则创建
        String imageDirPath = resultPath + formatDate;
        File imageDir = new File(imageDirPath);
        if (!imageDir.exists()){
            imageDir.mkdirs();
        }

        //3.2 拼接文件完整路径
        String imageFilePath = imageDirPath + "/" + newFileName;
        System.out.println(imageFilePath);

        //3.3 保存
        try {
            file.transferTo(new File(imageDir.getAbsoluteFile(), newFileName));

        } catch (Exception e){
            logger.error("文件 {} 保存失败", imageFilePath, e);
            return null;
        }

        //4.拼接请求路径

        //4.1 正则匹配请求前缀
        Pattern pattern = Pattern.compile("(.*)/upload.*");
        Matcher matcher = pattern.matcher(url);

        String urlPrefix = "http://localhost:18080";

        while(matcher.find()){
            urlPrefix = matcher.group(1);
        }
        return urlPrefix + "/image/resultpic/" + formatDate + newFileName;
    }

    /**
     * 商品图
     * */
    @Override
    public String uploadGoodsImage(String url, MultipartFile file) {
        //1.获取日期字符串
        String formatDate = sdf.format(new Date());

        //2.获取新文件名
        String newFileName = getNewFileName(file.getOriginalFilename());

        //3.保存图片

        //3.1 判断文件夹是否存在，不存在则创建
        String imageDirPath = goodsPath + formatDate;
        File imageDir = new File(imageDirPath);
        if (!imageDir.exists()){
            imageDir.mkdirs();
        }

        //3.2 拼接文件完整路径
        String imageFilePath = imageDirPath + "/" + newFileName;
        System.out.println(imageFilePath);

        //3.3 保存
        try {
            file.transferTo(new File(imageDir.getAbsoluteFile(), newFileName));

        } catch (Exception e){
            logger.error("文件 {} 保存失败", imageFilePath, e);
            return null;
        }

        //4.拼接请求路径

        //4.1 正则匹配请求前缀
        Pattern pattern = Pattern.compile("(.*)/upload.*");
        Matcher matcher = pattern.matcher(url);

        String urlPrefix = "http://localhost:18080";

        while(matcher.find()){
            urlPrefix = matcher.group(1);
        }
        return urlPrefix + "/image/goods/" + formatDate + newFileName;
    }

    @Override
    public String txMatting(String url, String picUrl) {
        GetObjectRequest getObj = new GetObjectRequest(bucketName, "");
        getObj.putCustomQueryParameter("ci-process", "AIPicMatting");
        getObj.putCustomQueryParameter("detect-url", picUrl);
        //1.获取日期字符串
        String formatDate = sdf.format(new Date());

        //2.获取新文件名
        String newFileName = getNewFileName("demo.png");

        //3.保存图片

        //3.1 判断文件夹是否存在，不存在则创建
        String imageDirPath = commonPath + formatDate;
        File imageDir = new File(imageDirPath);
        if (!imageDir.exists()){
            imageDir.mkdirs();
        }

        //3.2 拼接文件完整路径
        String imageFilePath = imageDirPath + "/" + newFileName;
        ObjectMetadata object = cosClient2.getObject(getObj, new File(imageFilePath));
        if(object.getContentLength() <= 0) {
            logger.error("【抠图失败】");
            return null;
        }
        Pattern pattern = Pattern.compile("(.*)/upload.*");
        Matcher matcher = pattern.matcher(url);

        String urlPrefix = "http://localhost:8883";

        while(matcher.find()){
            urlPrefix = matcher.group(1);
        }
        return urlPrefix + "/image/common/" + formatDate + newFileName;
    }

    /**
     * 根据旧文件名生成新文件名，使用 uuid 生成
     * @param oldName 旧文件名
     * @return 新文件名
     */
    public String getNewFileName(String oldName){

        //1.旧名称判空（这里使用了 hutools）
        if (StrUtil.isEmpty(oldName)){
            return null;
        }

        //2.正则匹配获取文件后缀
        Pattern sufixPattern = Pattern.compile(".*(\\..*)");
        Matcher matcher = sufixPattern.matcher(oldName);

        //3.UUID 生成文件新名称（这里使用了 hutools）
        String newFileName = UUID.randomUUID().toString();
        if (matcher.find()){
            newFileName += matcher.group(1);
        }

        //4.返回新名称
        return newFileName;
    }
}
